#!/usr/bin/env python
# encoding: utf-8
"""
searchmodel.py

Created by AlanYang on 2011-06-20.
Copyright (c) 2011 __MyCompanyName__. All rights reserved.
"""
import types
import redis
import cPickle
from functools import wraps

import searchengine
from flask import g
from application import app
from mongomodel import MongoModel


def add_job(*args):
    if not getattr(g,'redis',None):
        g.redis = channel = redis.Redis(app.config['REDIS_HOST'],app.config['REDIS_PORT'],app.config['DB_REDIS_SEARCH'])
    else:
        #g.redis.select(app.config['DB_REDIS_SEARCH'])
        assert g.redis.lpush(app.config['JOBS_KEY'],cPickle.dumps(args))

def update(indexfield,opera,fieldname,name=None,remote=True):
    """
    update document item
    opera support '$push' and '$set' 
    exp:
    @update(['answer','uid'],'$push','answers','question')
    def setanswer(qid,answer):
        pass
    """
    def __magic__(func):
        @wraps(func)
        def __do__(_id,obj):
            result = func(_id,obj)
            if type(obj) == types.DictType:
                docid = SearchModel().getsearchid(_id)
                if docid and not remote:
                    searchengine.update(docid,opera,indexfield,dict(( (fieldname,obj),)) )
                elif docid and remote:
                    add_job('update',docid,opera,indexfield,dict(( (fieldname,obj),)),name)
            return result
        return __do__
    return __magic__

def replace_index(indexfield,name=None):
    """docstring for reindex"""
    """
    mongo model save warp for search engine
    exp:
    
    @reindex(['name','nick'],name='user')
    def changeuser(uid,user):
        return UserModel().changeuser(uid,user)
    """
    def __magic__(func):
        @wraps(func)
        def __do__(_id,obj):
            result = func(_id,obj)
            if type(obj) == types.DictType and result:
                docid = SearchModel().getsearchid(_id)
                if docid:
                    obj['_id'] = _id
                    obj['name'] = name
                    sid = searchengine.index(indexfield,obj,docid=docid)
            return result
        return __do__
    return __magic__

def index(indexfield,name=None,remote=True):
    """
    mongo model save warp for search engine
    exp:
    
    @index(['name','nick'],'user',False)
    def setuser(user):
        return UserModel(**user).commit()
    """
    def __magic__(func):
        @wraps(func)
        def __do__(obj):
            _id = func(obj)
            if type(obj) == types.DictType and _id:
                obj['_id'] = _id
                obj['name'] = name
                if remote:
                    add_job('index',indexfield,obj,name)
                else:
                    sid = searchengine.index(indexfield,obj,name)
                    SearchModel(_id=_id,sid=sid,name=name).commit()
            return _id
        return __do__
    return __magic__
            
            

class SearchModel(MongoModel):
    """
    mongo id <_id> mapping to search id <sid> 
    """
    def __init__(self,**ids):
        self.ids = ids
        if not getattr(g, 'mongo',None):
            g.mongo = pymongo.Connection(app.config['MONGO_HOST'],app.config['MONGO_PORT'])
        MongoModel.__init__(self, g.mongo.freeasker.search, '_id', None, 0)
        
    def commit(self):
        if not self.ids:
            self.lasterror = 'Empty ids'
            return False
        if not self.ids.has_key('_id') or not self.ids.has_key('sid'):
            self.lasterror = 'ids has not _id or sid'
            return False
        return self.save(**self.ids)
    
    def getsearchid(self,_id):
        return self.get(_id=_id).get('sid',None)
